﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using MH.CRM.Summary.CrmSdk;
using System.Windows.Browser;
using System.Collections.ObjectModel;
using System.Windows.Media.Imaging;
using System.Collections;
using System.Text;

namespace MH.CRM.Summary
{
    public partial class MainPage : UserControl
    {
        #region "Private variables"
        private const int pageSize = 100;
        private int page = 1;
        ObservableCollection<EntityMetadata> entitiesMetadata;
        System.Collections.ObjectModel.ObservableCollection<object> ids = new ObservableCollection<object>();
       IDictionary<string, string> initParams;
        private HyperlinkButton hyperlinkLoadMore = new HyperlinkButton();
        bool isProjectActivitiesRetrieved = false;
        bool isRelatedEntitiesActivitiesRetrieved = false;
        ObservableCollection<Entity> activities = new ObservableCollection<Entity>();
        #endregion

        #region "Event Handlers"
        public static DateTime BestDate(Entity activity)
        {
            //if (activity.Attributes.ContainsKey("actualend"))
            //{
            //    return activity.GetAttributeValue<DateTime>("actualend");
            //}
            //else if (activity.Attributes.ContainsKey("scheduledend"))
            //{
            //    return activity.GetAttributeValue<DateTime>("scheduledend");
            //}
            //else
            //{
                return activity.GetAttributeValue<DateTime>("createdon");
           // }
        }

        public MainPage(App app, IDictionary<string,string> initParams)
        {
            InitializeComponent();
            this.initParams = initParams;            
            app.UnhandledException += new EventHandler<ApplicationUnhandledExceptionEventArgs>(app_UnhandledException);
            hyperlinkLoadMore.Content = "Load more...";
            hyperlinkLoadMore.Click += new RoutedEventHandler(hyperlinkLoadMore_Click);
            Loaded += new RoutedEventHandler(MainPage_Loaded);            
        }

        void hyperlinkLoadMore_Click(object sender, RoutedEventArgs e)
        {
            this.page++;
            this.listBoxActivities.Items.Clear();
            this.TextBlockDate.Text = "";
            this.TextBlockDescription.Text = "";
            this.TextBlockFrom.Text = "";
            this.TextBlockSubject.Text = "";
            this.TextBlockTo.Text = "";
          //  this.listBoxActivities.Items.Remove(hyperlinkLoadMore);
            isProjectActivitiesRetrieved = false;
            isRelatedEntitiesActivitiesRetrieved = false;
            string typename = initParams["typename"];
            if (typename.ToLower() == "account" || typename.ToLower() == "contact")
            {
                if (ids.Count > 0)
                {
                    RollupProjectActivities();
                }
                ActivityRollupReqest();
            }
            else
            {
                ActivityQueryRequest();
            }
        }

        private void ReportError(Exception ex)
        {
            this.ReportMessage("Exception: " + SilverlightUtility.ConvertToString(ex));
        }

        private void ReportMessage(string message)
        {
            this.Dispatcher.BeginInvoke(() => 
                {
                    MessageBox.Show(message);
                    this.BusyIndicator.IsBusy = false;
                });
        }

        private void app_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
        {
            this.ReportError(e.ExceptionObject);
        }

        void MainPage_Loaded(object sender, RoutedEventArgs e)
        {

            if (!initParams.ContainsKey("id") || String.IsNullOrEmpty(initParams["id"]))
            {
                this.HyperlinkButtonRefresh.IsEnabled = false;
                BusyIndicator.IsBusy = false;
                return;
            }
            RetrieveRelatedProjects();
            RetrieveAllEntitiesReqest();    
        }
        #endregion
        
        #region "Retrieve All Entities Metadata"
        private void RetrieveAllEntitiesReqest()
        {
            IOrganizationService service = SilverlightUtility.GetSoapService();
            OrganizationRequest retriveAllEntitiesReqest = new OrganizationRequest() { RequestName = "RetrieveAllEntities" };
            retriveAllEntitiesReqest["EntityFilters"] = EntityFilters.Entity;
            retriveAllEntitiesReqest["RetrieveAsIfPublished"] = false;

            service.BeginExecute(retriveAllEntitiesReqest, new AsyncCallback(RetriveAllEntities_Callback), service);
        }

        private void RetriveAllEntities_Callback(IAsyncResult result)
        {
            OrganizationResponse response;

            try
            {
                response = ((IOrganizationService)result.AsyncState).EndExecute(result);
                entitiesMetadata = (ObservableCollection<EntityMetadata>)response["EntityMetadata"];
            }
            catch
            {
                this.listBoxActivities.Dispatcher.BeginInvoke(() =>
                {
                    MessageBox.Show("Activity Summary extension cannot connect to crm server. Make sure you connect to CRM with following url: " + SilverlightUtility.GetServerBaseUrl());
                });
                return;
            }

            this.listBoxActivities.Dispatcher.BeginInvoke(() =>
            {
                //Add "Add New acitivity" buttons
                foreach (EntityMetadata entityMetadata in from el in entitiesMetadata
                                                          where el.IsActivity == true
                                                          && (el.IsCustomEntity == true || el.ObjectTypeCode == 4212 || el.ObjectTypeCode == 4202
                                                          || el.ObjectTypeCode == 4210 || el.ObjectTypeCode == 4204 || el.ObjectTypeCode == 4207
                                                          || el.ObjectTypeCode == 4201 || el.ObjectTypeCode == 4214)
                                                          orderby el.ObjectTypeCode
                                                          select el)
                {

                    Image imageNewActivity = new Image();
                    imageNewActivity.Tag = entityMetadata;
                    imageNewActivity.Stretch = Stretch.None;
                    if (entityMetadata.IsCustomEntity == false)
                    {
                        imageNewActivity.Source = new BitmapImage(new Uri("/MH.CRM.Summary;component/imgs/ico_16_" + entityMetadata.ObjectTypeCode + ".png", UriKind.Relative)); ;
                    }
                    else if (entityMetadata.IconSmallName == null)
                    {
                        imageNewActivity.Source = new BitmapImage(new Uri("/MH.CRM.Summary;component/imgs/ico_16_CustomActivity.png", UriKind.Relative));
                    }
                    else
                    {
                        imageNewActivity.Source = new BitmapImage(new Uri(SilverlightUtility.GetServerBaseUrl() + "/WebResources/" + entityMetadata.IconSmallName, UriKind.Absolute));
                    }

                    imageNewActivity.Margin = new Thickness(2);

                    HyperlinkButton buttonNewActivity = new HyperlinkButton();
                    buttonNewActivity.Tag = entityMetadata;
                    buttonNewActivity.Content = imageNewActivity;
                    buttonNewActivity.Margin = new Thickness(10, 2, 2, 2);
                    buttonNewActivity.Width = 20;
                    buttonNewActivity.Click += new RoutedEventHandler(buttonNewActivity_Click);

                    Style style = Application.Current.Resources["ImageButton"] as Style;
                    buttonNewActivity.Style = style;

                    this.PanelButtons.Children.Add(buttonNewActivity);
                }

                isProjectActivitiesRetrieved = false;
                isRelatedEntitiesActivitiesRetrieved = false;
                activities.Clear();
                string typename = initParams["typename"];
                if (typename.ToLower() == "account" || typename.ToLower() == "contact")
                {
                    if (ids.Count > 0)
                    {
                        RollupProjectActivities();
                    }
                    else
                    {
                        isProjectActivitiesRetrieved = true;
                    }
                    ActivityRollupReqest();
                }
                else
                {
                    ActivityQueryRequest();
                }
            });
        }

        #endregion

        #region "Retrieve All activites of related entities"
        private void ActivityRollupReqest()
        {
            BusyIndicator.IsBusy = true;

            IOrganizationService service = SilverlightUtility.GetSoapService();
            //Get object type and id
            Guid objectid = new Guid(initParams["id"]);
            string typename = initParams["typename"];

            OrganizationRequest rollupReqest = new OrganizationRequest() { RequestName = "Rollup" };
            if (typename.ToLower() == "account" || typename.ToLower() == "contact")
            {
                rollupReqest["RollupType"] = RollupType.Related;
            }
            else
            {
                rollupReqest["RollupType"] = RollupType.None;
            }
            rollupReqest["Target"] = new EntityReference()
            {
                Id = objectid,
                LogicalName = typename
            };
            rollupReqest["Query"] = new QueryExpression()
            {
                ColumnSet = new ColumnSet()
                {
                    AllColumns = true
                },
                EntityName = "activitypointer",
                //Orders = new ObservableCollection<OrderExpression>()
                //{
                //    new OrderExpression()
                //    {
                //        AttributeName = "modifiedon",
                //        OrderType = OrderType.Descending
                //    }
                //},
                PageInfo = new PagingInfo()
                {
                    PageNumber = page,
                    Count = pageSize
                }
            };

            service.BeginExecute(rollupReqest, new AsyncCallback(ActivityRollup_Callback), service);
        }

        private void ActivityRollup_Callback(IAsyncResult result)
        {            
            OrganizationResponse response = ((IOrganizationService)result.AsyncState).EndExecute(result);
            EntityCollection results = (EntityCollection)response["EntityCollection"];
             foreach (Entity entity in results.Entities )
             {
                 activities.Add(entity);
             }
             if (isProjectActivitiesRetrieved)
             {
                 this.listBoxActivities.Dispatcher.BeginInvoke(() =>
                 {
                     BusyIndicator.IsBusy = false;
                     foreach (Entity entity in from el in activities orderby BestDate(el) descending select el)
                     {
                         EntityMetadata activityMetadata = (from el in entitiesMetadata where el.LogicalName == entity.GetAttributeValue<string>("activitytypecode") select el).First();
                         ActivityRow activityRow = new ActivityRow();
                         listBoxActivities.Items.Add(activityRow);
                         activityRow.Init(entity, activityMetadata);
                     }

                     if (results.MoreRecords)
                     {
                         listBoxActivities.Items.Add(hyperlinkLoadMore);
                     }
                 });
             }
             else
             {
                 isRelatedEntitiesActivitiesRetrieved = true;
             }
        }
        #endregion

        #region "Retrieve Activities related to projects"
        private void RollupProjectActivities()
        {
            IOrganizationService service = SilverlightUtility.GetSoapService();
            //Get object type and id
            //Guid objectid = new Guid("DEF2E3DA-2E7D-E211-8C63-78E3B50829E1");
            
            string typename = initParams["typename"];
            OrganizationRequest retrieveMultipleReqest = new OrganizationRequest() { RequestName = "RetrieveMultiple" };
           
            QueryExpression query = new QueryExpression()
            {
                EntityName = "activitypointer",
                ColumnSet = new ColumnSet()
                {
                    AllColumns = true
                },
                Criteria = new FilterExpression()
                {
                    Conditions = new System.Collections.ObjectModel.ObservableCollection<ConditionExpression>() 
                    { 
                        new ConditionExpression() { AttributeName = "regardingobjectid", Operator = ConditionOperator.In , Values = ids },                            
                    }
                },
                //Orders = new ObservableCollection<OrderExpression>()
                //{
                //    new OrderExpression()
                //    {
                //        AttributeName = "modifiedon",
                //        OrderType = OrderType.Descending
                //    }
                //},
                PageInfo = new PagingInfo()
                {
                    PageNumber = page,
                    Count = pageSize
                }
            };
            retrieveMultipleReqest["Query"] = query;
            service.BeginExecute(retrieveMultipleReqest, new AsyncCallback(ProjectActivityRollup_Callback), service);
        }

        private void ProjectActivityRollup_Callback(IAsyncResult result)
        {
            OrganizationResponse response = ((IOrganizationService)result.AsyncState).EndExecute(result);
            EntityCollection results = (EntityCollection)response["EntityCollection"];
            foreach (Entity entity in results.Entities)
            {
                activities.Add(entity);
            }
            if (isRelatedEntitiesActivitiesRetrieved)
            {
                this.listBoxActivities.Dispatcher.BeginInvoke(() =>
                {
                    BusyIndicator.IsBusy = false;
                    foreach (Entity entity in from el in activities orderby BestDate(el) descending select el)
                    {
                        EntityMetadata activityMetadata = (from el in entitiesMetadata where el.LogicalName == entity.GetAttributeValue<string>("activitytypecode") select el).First();
                        ActivityRow activityRow = new ActivityRow();
                        activityRow.Init(entity, activityMetadata);
                        listBoxActivities.Items.Add(activityRow);
                    }

                    if (results.MoreRecords)
                    {
                        listBoxActivities.Items.Add(hyperlinkLoadMore);
                    }
                });
            }
            else
            {
                isProjectActivitiesRetrieved = true;
            }
        }
        #endregion

        #region "Retrieve Related Projects"
        private void RetrieveRelatedProjects()
        {
            IOrganizationService service = SilverlightUtility.GetSoapService();
            //Get object type and id
            Guid objectid = new Guid(initParams["id"]);
            string typename = initParams["typename"];

            OrganizationRequest retrieveMultipleReqest = new OrganizationRequest() { RequestName = "RetrieveMultiple" };
            QueryExpression query = new QueryExpression()
            {
                EntityName = "neu_project",
                ColumnSet = new ColumnSet()
                {
                    AllColumns = true
                },
                Criteria = new FilterExpression()
                {
                    Conditions = new System.Collections.ObjectModel.ObservableCollection<ConditionExpression>() 
                    { 
                        new ConditionExpression() { AttributeName = "neu_account", Operator = ConditionOperator.Equal , Values = new System.Collections.ObjectModel.ObservableCollection<object>() { objectid } },                            
                    }
                }
            };
            retrieveMultipleReqest["Query"] = query;
            service.BeginExecute(retrieveMultipleReqest, new AsyncCallback(RetriveRelatedProjects_Callback), service);
        }

        private void RetriveRelatedProjects_Callback(IAsyncResult result)
        {
            OrganizationResponse response = ((IOrganizationService)result.AsyncState).EndExecute(result);
            EntityCollection results = (EntityCollection)response["EntityCollection"];
            ids.Clear();
            foreach (Entity entity in from el in results.Entities select el)
            {
                ids.Add(entity.Id);
            }
        }
        #endregion

        #region "Retrieve Activities Related to Entity"
        private void ActivityQueryRequest()
        {
            BusyIndicator.IsBusy = true;

            IOrganizationService service = SilverlightUtility.GetSoapService();
            //Get object type and id
            Guid objectid = new Guid(initParams["id"]);
            string typename = initParams["typename"];

            OrganizationRequest retrieveMultipleReqest = new OrganizationRequest() { RequestName = "RetrieveMultiple" };
            QueryExpression query = new QueryExpression()
            {
                EntityName = "activitypointer",
                ColumnSet = new ColumnSet()
                {
                    AllColumns = true
                },
                Criteria = new FilterExpression()
                {
                    Conditions = new System.Collections.ObjectModel.ObservableCollection<ConditionExpression>() 
                    { 
                        new ConditionExpression() { AttributeName = "regardingobjectid", Operator = ConditionOperator.Equal , Values = new System.Collections.ObjectModel.ObservableCollection<object>() { objectid } },                            
                    }
                },
                Orders = new ObservableCollection<OrderExpression>()
                {
                    new OrderExpression()
                    {
                        AttributeName = "modifiedon",
                        OrderType = OrderType.Descending
                    }
                },
                PageInfo = new PagingInfo()
                {
                    PageNumber = page,
                    Count = pageSize
                }
            };
            retrieveMultipleReqest["Query"] = query;
            service.BeginExecute(retrieveMultipleReqest, new AsyncCallback(RetrieveActivities_Callback), service);
        }
        
        private void RetrieveActivities_Callback(IAsyncResult result)
        {
            OrganizationResponse response = ((IOrganizationService)result.AsyncState).EndExecute(result);
            EntityCollection results = (EntityCollection)response["EntityCollection"];

            this.listBoxActivities.Dispatcher.BeginInvoke(() =>
            {
                BusyIndicator.IsBusy = false;
                foreach (Entity entity in from el in results.Entities orderby BestDate(el) descending select el)
                {
                    EntityMetadata activityMetadata = (from el in entitiesMetadata where el.LogicalName == entity.GetAttributeValue<string>("activitytypecode") select el).First();
                    ActivityRow activityRow = new ActivityRow();
                    activityRow.Init(entity, activityMetadata);                    
                    listBoxActivities.Items.Add(activityRow);                      
                }

                if (results.MoreRecords)
                {                    
                        listBoxActivities.Items.Add(hyperlinkLoadMore);
                } 
            });
        }
        #endregion

        #region "Create new activity"
        void buttonNewActivity_Click(object sender, RoutedEventArgs e)
        {
            EntityMetadata activityMetadata = (sender as HyperlinkButton).Tag as EntityMetadata;
            string link = SilverlightUtility.GetServerBaseUrl().ToString();
            string typename = initParams["typename"];
            if (typename.ToLower() == "account" || typename.ToLower() == "contact")
            {
                link += string.Format("/main.aspx?etc={0}&extraqs=%3fcontactInfo%3d%26etc%3d{0}%26pId%3d{1}%26pType%3d{2}%26pagemode%3diframe%26partyid%3d{1}%26partytype%3d{2}&pagetype=entityrecord",
                    activityMetadata.ObjectTypeCode, initParams["id"].Replace("{", "%257b").Replace("}", "%257d"), initParams["type"]);
            }
            else
            {
                link += string.Format("/main.aspx?etc={0}&extraqs=%3fcontactInfo%3d%26etc%3d{0}%26pId%3d{1}%26pType%3d{2}%26pagemode%3diframe&pagetype=entityrecord",
                    activityMetadata.ObjectTypeCode, initParams["id"].Replace("{", "%257b").Replace("}", "%257d"), initParams["type"]);
            }
            HtmlPage.Window.Navigate(new Uri(link), "_blank", "directories=no,fullscreen=no,menubar=no,resizable=yes,scrollbars=yes,status=no,titlebar=yes,toolbar=no");
        }
        #endregion

        #region "Activities Selected IndexChange"
        private void listBoxActivities_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (listBoxActivities.SelectedItem != null)
            {
                BusyIndicator.IsBusy = true;
                ActivityRow activityRow = listBoxActivities.SelectedItem as ActivityRow;

                this.TextBlockSubject.Text = activityRow.Subject;
                this.TextBlockDate.Text = activityRow.Date;
                if (activityRow.Description != null)
                {
                    this.TextBlockDescription.Text = activityRow.Description;
                }
                else
                {
                    this.TextBlockDescription.Text = "";
                }
                if (activityRow.From != null)
                {
                    this.TextBlockFrom.Text = activityRow.From;
                }
                else
                {
                    this.TextBlockFrom.Text = "";
                }
                if (activityRow.To != null)
                {
                    this.TextBlockTo.Text = activityRow.To;
                }
                else
                {
                    this.TextBlockTo.Text = "";
                }
                 this.listAttachments.Items.Clear();
                if (activityRow.LogicalName.ToLower() == "email")
                {
                    RetrieveAttachments(activityRow);                   
                }

                BusyIndicator.IsBusy = false;
            }
        }
        #endregion
        
        #region "Retrieve Attachments"
       
        private void RetrieveAttachments(ActivityRow row)
        {
            
            IOrganizationService service = SilverlightUtility.GetSoapService();
            OrganizationRequest retrieveMultipleReqest = new OrganizationRequest() { RequestName = "RetrieveMultiple" };
            QueryExpression query = new QueryExpression()
            {
                EntityName = "activitymimeattachment",
                ColumnSet = new ColumnSet()
                {
                    AllColumns = true
                },
                PageInfo = new PagingInfo()
                {
                    PageNumber = 1,
                    Count = 100
                }
                ,
                Criteria = new FilterExpression()
                {
                    Conditions = new System.Collections.ObjectModel.ObservableCollection<ConditionExpression>() 
                    { 
                        new ConditionExpression() { AttributeName = "objectid", Operator = ConditionOperator.Equal , Values = new System.Collections.ObjectModel.ObservableCollection<object>() { row.Id } },                            
                        new ConditionExpression() { AttributeName = "objecttypecode", Operator = ConditionOperator.Equal , Values = new System.Collections.ObjectModel.ObservableCollection<object>() { row.LogicalName } }

                    }
                }
            };
            retrieveMultipleReqest["Query"] = query;
            service.BeginExecute(retrieveMultipleReqest, new AsyncCallback(RetrieveAttachments_Callback), service);
        }

        private void RetrieveAttachments_Callback(IAsyncResult result)
        {
            OrganizationResponse response = ((IOrganizationService)result.AsyncState).EndExecute(result);
            EntityCollection results = (EntityCollection)response["EntityCollection"];
            this.listAttachments.Dispatcher.BeginInvoke(() =>
            {
                BusyIndicator.IsBusy = false;
                foreach (Entity entity in from el in results.Entities orderby BestDate(el) descending select el)
                {
                    Attachment attachment = new Attachment();
                    attachment.Init(entity);
                    listAttachments.Items.Add(attachment);
                }
            });
        }
        #endregion

        #region "Refresh Grid"
        private void HyperlinkButtonRefresh_Click(object sender, RoutedEventArgs e)
        {
            page = 1;
            this.listBoxActivities.Items.Clear();
            this.TextBlockDate.Text = "";
            this.TextBlockDescription.Text = "";
            this.TextBlockFrom.Text = "";
            this.TextBlockSubject.Text = "";
            this.TextBlockTo.Text = "";
            string typename = initParams["typename"];
            isProjectActivitiesRetrieved = false;
            isRelatedEntitiesActivitiesRetrieved = false;
            activities.Clear();
            if (typename.ToLower() == "account" || typename.ToLower() == "contact")            
            {
                ActivityRollupReqest();
                if (ids.Count > 0)
                {
                    RollupProjectActivities();
                }
                else
                {
                    isProjectActivitiesRetrieved = true;
                }
            }
            else
            {
                ActivityQueryRequest();
            }
        }
        #endregion
    }
}
